﻿/**
 * FileSys类及FileNode类定义
 * 完成文件系统结构的定义
 */

#ifndef FILESYS_H
#define FILESYS_H

#include "MyString.h"
#include "ErrMsg.h"
#include <string.h>
#include <time.h>

/**
 * 定义路径节点基类
 */
class FileNode
{
public:
    FileNode();
    FileNode(MyString &name, time_t time);
    ~FileNode();
    
    virtual bool isLeaf() const = 0;

    virtual void setParent(FileNode *parent) { m_parent = parent; }
    virtual void setBrother(FileNode *brother) { m_brother = brother; }
    virtual void setChild(FileNode *child) {}

    virtual void setName(MyString &name) { m_name = name; }
    virtual void setTime(time_t time) { m_time = time; }

    virtual FileNode *getParent() const { return m_parent; }
    virtual FileNode *getBrother() const { return m_brother; }
    virtual FileNode *getChild() const { return NULL; };

    virtual MyString getName() const { return m_name; }
    virtual time_t getTime() const { return m_time; }

    virtual void setFile(char *file_data, int size) {}
    virtual void setBinary(bool binary) {}
    virtual char *getFileData() const { return NULL; }
    virtual int getSize() const { return 0; }
    virtual bool isBinary() const { return false; }

protected:
    FileNode *m_parent;
    FileNode *m_brother;
    
    MyString m_name;
    time_t m_time;
};

/**
 * 定义文件节点，继承自FileNode
 */
class LeafNode : public FileNode
{
public:
    LeafNode();
    LeafNode(MyString &name, time_t time);
    LeafNode(MyString &name, time_t time, char *file_data, int size);
    ~LeafNode();

    virtual bool isLeaf() const { return true; }
    
    virtual void setFile(char *file_data, int size);
    virtual void setBinary(bool binary) { m_binary = binary; }
    virtual char *getFileData() const { return m_file_data; }
    virtual int getSize() const { return m_size; }
    virtual bool isBinary() const { return m_binary; }

private:
    char *m_file_data;
    int m_size;
    bool m_binary;
};

/**
 * 定义目录节点，继承自FileNode
 */
class BranchNode : public FileNode
{
public:
    BranchNode();
    BranchNode(MyString &name, time_t time);
    ~BranchNode();

    virtual bool isLeaf() const { return false; }
    
    virtual void setChild(FileNode *child) { m_child = child; }
    virtual FileNode *getChild() const { return m_child; }

private:
    FileNode *m_child;
};

/**
 * 定义文件系统（文件树）
 */
class FileSys
{
public:
    FileSys();
    ~FileSys();

    int Cd(MyString &path);  // 转换路径
    int Compare(MyString &realPath, MyString &virtualPath);  // 比较两个文件是否相等
    int DirSub(MyString &path, bool isDirectory);  // "dir /ad" "dir"
    int DirSubAll(MyString &path, bool isDirectory); // "dir /ad/s" "dir /s"
    int Rmdir(MyString &path, bool isSubAll);  // 删除路径
    int Mkdir(MyString &path);  // 创建路径
    int Del(MyString &path, bool isSubAll);  // 删除文件
    int Copy(MyString &realPath, MyString &virtualPath);  // 拷贝文件

    MyString &getPathStr(MyString &ret_path, FileNode *path_node);  // 获得节点path_node的绝对路径

    int checkPath(MyString &path);  // 检查输入路径是否合法
    FileNode *findPath(MyString &path, FileNode **ret_node = NULL, int *pos = NULL);  // 从路径字符串转换为FileNode指针
    FileNode *findPath(MyString &path, FileNode *ret_node);  // 找到节点ret_node的子节点中的path

    bool checkNode(FileNode *parent, MyString &name, FileNode *&retNode);  // 检查名为name的节点是否是parent的子节点
    FileNode *createNode(MyString &name, FileNode *node, time_t t = NULL, char *data = NULL, int size = 0);  // 新建节点
    int createNode(MyString &path, FileNode *node, int startPos);  // 根据路径新建节点及其子节点
    int copyFile(MyString &realPath, MyString &virtualPath,
        FileNode *parentNode, FileNode *curNode, bool canSub);  // 查找真实磁盘下的文件，拷贝到curNode，返回拷贝文件的数目

    void delNode(FileNode *node);  // 删除节点node
    void delSubNode(FileNode *node);  // 删除子节点中的Leaf节点
    int delSubNode(FileNode *node, MyString &name);  // 删除子节点中的(通配符)名为name的Leaf节点
    void traverseDel(FileNode *node);  // 删除当前及其子目录下所有节点
    void traverseDelLeaf(FileNode *node);  // 删除当前节点及其子目录下的Leaf节点
    int traverseDelLeaf(FileNode *node, MyString &name);  // 删除当前节点及其子目录下的(通配符)名为name的Leaf节点

    void printNode(FileNode *curNode, int &numFile, int &numDir);  // 格式化打印节点信息
    void printDir(FileNode *curNode, bool isDirectory, int &numFile, int &numDir);  // dir打印节点信息
    void printDir(FileNode *curNode, int &numFile, int &numDir, MyString &name);  // dir打印名为name的节点信息
    void traverseDir(FileNode *curNode, bool isDirectory, int &numFile, int &numDir);  // 遍历dir打印节点信息
    void traverseDir(FileNode *curNode, int &numFile, int &numDir, MyString &name);  // 遍历dir打印名为name的节点信息

    void showCurPath();  // 打印当前路径
    int readFile(MyString &path, char *&fileData, int &len);  // 从实际磁盘读取文件
    bool isBinary(char *buf, int len);  // 判断文件是否是二进制文件
    void printNotMatch(unsigned char *buf, int pos, bool isBinary);  // Compare函数发生不匹配时，打印信息
    void getDirAndFile(MyString &realPath, MyString &dir, MyString &file);  // 获取倒数第二层路径（即目录）
    bool existDir(MyString &path, int start);  // 判断path[start]后面是否存在目录

private:
    FileNode *m_root_node;
    FileNode *m_cur_node;
    static const int COMPARE_PRINT_LEN;
    static const int MAX_PATH_NAME_LEN;
};

#endif